package yyds.sniarbtej.transformer.dbvisualizer;

import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.*;
import yyds.sniarbtej.transformer.BaseClassTransformer;
import yyds.sniarbtej.transformer.ClassRewriter;

import java.util.List;

public class SkipSignature extends BaseClassTransformer {
    public String canTransformClassName() {
        return "sun/security/provider/DSA$SHA1withDSA";
    }

    public byte[] rewrite(byte[] in) {
        return transform(in, new ClassRewriter() {
            @Override
            public void addMethods(List<MethodNode> node) {
                MethodNode newMethod = new MethodNode(Opcodes.ACC_PROTECTED, "engineVerify", "([B)Z", null, null);
                InsnList insn = new InsnList();

                // Load 'this'
                insn.add(new VarInsnNode(Opcodes.ALOAD, 0));
                // Load sigBytes
                insn.add(new VarInsnNode(Opcodes.ALOAD, 1));
                // Create a new object String using sigBytes
                insn.add(new TypeInsnNode(Opcodes.NEW, "java/lang/String"));
                insn.add(new InsnNode(Opcodes.DUP)); // Duplicate the object for ctor
                insn.add(new VarInsnNode(Opcodes.ALOAD, 1)); // Load sigBytes
                insn.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, "java/lang/String", "<init>", "([B)V", false)); // Init new object String

                // Compare the new object String with ALWAYS VERIFIED SEAL
                insn.add(new LdcInsnNode("ALWAYS VERIFIED SEAL")); // Load String
                insn.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false)); // Chiama equals
                LabelNode label1 = new LabelNode();
                insn.add(new JumpInsnNode(Opcodes.IFEQ, label1)); // If not equal go to label1

                // Return true
                insn.add(new InsnNode(Opcodes.ICONST_1));
                insn.add(new InsnNode(Opcodes.IRETURN));

                insn.add(label1);
                insn.add(new VarInsnNode(Opcodes.ALOAD, 0)); // Load 'this'
                insn.add(new VarInsnNode(Opcodes.ALOAD, 1)); // Load sigBytes
                insn.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, "java/security/SignatureSpi", "engineVerify", "([B)Z", false)); // Call super.engineVerify
                insn.add(new InsnNode(Opcodes.IRETURN)); //

                newMethod.instructions.add(insn);
                node.add(newMethod); // Add the new method to the class
            }
        });
    }
}
